<template>
	<div class="scrollbar-box">
		<template v-if="open">
			<div :class="['my-scrollbar',{'horizontal': horizontal},{'vertical': vertical},{'visible': visible || vflag || hflag}]"
			     @mousewheel="mousewheelhander">
				<div  :class="horizontalClass"
				     v-if="horizontal"
					 v-show="horizontal_thumb_width"
				     ref="horizontal-bar"
				     @click.stop="clickHBar">
					<div :class="['scrollbar_thumb',{'move': hflag}]"
					     :style="renderThumbStyle('x')"
					     @mousedown="horizontalScroll"
					     @click.stop>
					</div>
				</div>
				<div :class="verticalClass"
				     v-if="vertical"
					 v-show="vertical_thumb_height"
				     ref="vertical-bar"
				     @click.stop="clickVBar">
					<Icon v-if="arrow" type="arrow-up-b" :class="{'disabled': upDisabled}"  @click.native.stop="upWard" @mousedown.native="topDown = true" @mouseup.native="topDown = false"></Icon>
					<div :class="['scrollbar_thumb',{'move': vflag}]"
					     :style="renderThumbStyle('y')"
					     @mousedown="verticalScroll($event)"
					     @click.stop>
					</div>
					<Icon v-if="arrow" type="arrow-down-b"  :class="['thumb-d', {'disabled': downDisabled}]" @click.native.stop="down" @mousedown.native="botDown = true" @mouseup.native="botDown = false"></Icon>
				</div>
				<div class="scrollbar_wrap"
				     ref="scrollbar-wrap"
				     >
					<div class="scrollbar_view"
					     ref="scrollView">
						<slot></slot>
					</div>
				</div>
			</div>
		</template>
		<template v-else>
			<div class="common-scrollbar">
				<slot></slot>
			</div>
		</template>
	</div>
</template>
<script>
import { on, off, findScroller } from '@/common/dom';
export default {
	props: {
		open: {
			type: Boolean,
			default: true,
		},
		top: Boolean,
		left: Boolean,
		horizontal: Boolean,
		vertical: Boolean,
		visible: Boolean,
		axisY: {
			type: Number,
			default: 0,
		},
		axisX: {
			type: Number,
			default: 0,
		},
		arrow: {
			type: Boolean,
			default: false,
		},
	},
	data() {
		return {
			wrap_height: 0,
			wrap_width: 0,
			scroll_width: 0,
			scroll_height: 0,
			view_height: 0,
			view_width: 0,
			bar_width: 0,
			bar_height: 0,
			horizontal_thumb_width: 0,
			horizontal_thumb_translate: 0,
			vertical_thumb_height: 0,
			vertical_thumb_translate: 0,
			scrollTop: 0,
			scrollLeft: 0,
			vflag: false,
			vstart: 0,
			hflag: false,
			hstart: 0,
			vClick: false,
			hClick: false,
			topDown: false,
			botDown: false,
			interval: null,
			downDisabled: false,
			upDisabled: false
		};
	},
	computed: {
		horizontalClass() {
			if (this.top) {
				return 'scrollbar_bar is-horizontal top';
			} else {
				return 'scrollbar_bar is-horizontal';
			}
		},
		verticalClass() {
			if (this.left) {
				return 'scrollbar_bar is-vertical left';
			} else {
				return 'scrollbar_bar is-vertical';
			}
		},
	},
	watch: {
		axisY: function(val) {
			if (!this.vflag) {
				let Y = (this.bar_height - this.vertical_thumb_height) * val / (this.scroll_height - this.wrap_height);
				let disY = Y - this.vertical_thumb_translate;
				this.setTop(disY);
			}
		},
		axisX: function(val) {
			if (!this.hflag) {
				let X = (this.bar_width - this.horizontal_thumb_width) * val / (this.scroll_width - this.wrap_width);
				let disX = X - this.horizontal_thumb_translate;
				this.setLeft(disX);
			}
		},
		horizontal_thumb_width: function(now, old) {
			if (now) {
				this.$emit('on-show', { axis: 'x' });
			} else {
				this.$emit('on-hidden', { axis: 'x' });
			}
		},
		vertical_thumb_height: function(now, old) {
			if (now) {
				this.$emit('on-show', { axis: 'y' });
			} else {
				this.$emit('on-hidden', { axis: 'y' });
			}
		},
		topDown(val) {
		clearInterval(this.interval)
		if (val) {
			this.interval = setInterval(() => {
				this.upWard();
			},200)
			} else {
				clearInterval(this.interval)
			}
		},
		botDown(val) {
		clearInterval(this.interval)
		if (val) {
			this.interval = setInterval(() => {
				this.down();
			},200)
			} else {
				clearInterval(this.interval)
			}
		},
		vertical_thumb_translate(val) {
        if (val === 0) {
			this.upDisabled = true
		} else if (val === (this.bar_height - this.vertical_thumb_height)) {
            this.downDisabled = true 
		} else {
			this.upDisabled = false
			this.downDisabled = false 
		}
		}
	},
	methods: {
		upWard() {
		if (this.upDisabled) return;
		let disY;
		if (this.bar_height - this.vertical_thumb_height <= 100) {
           disY = -20;
		} else {
           disY = -((this.bar_height - this.vertical_thumb_height) * 0.05);
		}
		this.setTop(disY);
		},
		down() {
		if (this.downDisabled) return;
		let disY;
		if (this.bar_height - this.vertical_thumb_height <= 100) {
           disY = 20;
		} else {
           disY = (this.bar_height - this.vertical_thumb_height) * 0.05;
		}
		this.setTop(disY);
		},
		mousewheelhander(e) {
			if (!this.vertical) return;
			if (!this.vertical_thumb_height) return;
			// TODO: 对于scrollbar嵌套情况的处理
			//对触发滚动的元素进行判断，若其带有远程滚动条属性，则不进行组件滚动处理
			//当触发事件的远程滚动无法滚动时(到达顶部或底部)，则进行组件滚动处理
			var wheelUp = e.wheelDelta > 0 || e.detail > 0;
			var wheelDown = e.wheelDelta < 0 || e.detail < 0;
			//寻找当前元素的上级滚动元素
			var scrollElement = findScroller(e.target, this.$refs['scrollbar-wrap']);
			if (
				!scrollElement ||
				(wheelUp && scrollElement.scrollTop <= 0) ||
				(wheelDown && scrollElement.scrollTop + scrollElement.clientHeight >= scrollElement.scrollHeight)
			) {
				e.stopPropagation();
				e.preventDefault();
				if (wheelUp) {
					let disY = -((this.bar_height - this.vertical_thumb_height) * 0.05);
					if (this.vertical_thumb_translate !== 0) {
						this.setTop(disY);
					}
				}
				if (wheelDown) {
					let disY = (this.bar_height - this.vertical_thumb_height) * 0.05;
					if (this.vertical_thumb_translate < this.bar_height - this.vertical_thumb_height) {
						this.setTop(disY);
					}
				}
			}
		},
		thumbSize() {
			var scrollbarWrap = this.$refs['scrollbar-wrap'];
			this.wrap_height = scrollbarWrap.offsetHeight;
			this.wrap_width = scrollbarWrap.offsetWidth;
			this.scroll_width = scrollbarWrap.scrollWidth;
			this.scroll_height = scrollbarWrap.scrollHeight;
			this.view_height = scrollbarWrap.children[0].offsetHeight;
			this.view_width = scrollbarWrap.children[0].offsetWidth;
			this.bar_width = this.wrap_width;
			if (this.arrow) {
             this.bar_height = this.wrap_height - 26;
			} else {
             this.bar_height = this.wrap_height 
			}
			if (this.horizontal && this.scroll_width > this.wrap_width) {
				this.horizontal_thumb_width = parseInt(this.bar_width * this.wrap_width / this.scroll_width);
				if (this.horizontal_thumb_width < 20) this.horizontal_thumb_width = 20;
			} else {
				this.horizontal_thumb_width = 0;
			}
			if (this.vertical && this.scroll_height > this.wrap_height) {
				this.vertical_thumb_height = parseInt(this.bar_height * this.wrap_height / this.scroll_height);
				if (this.vertical_thumb_height < 20) this.vertical_thumb_height = 20;
			} else {
				this.vertical_thumb_height = 0;
			}
			this.vertical_thumb_translate =
				(this.bar_height - this.vertical_thumb_height) *
				scrollbarWrap.scrollTop /
				(this.scroll_height - this.wrap_height);
			this.horizontal_thumb_translate =
				(this.bar_width - this.horizontal_thumb_width) *
				scrollbarWrap.scrollLeft /
				(this.scroll_width - this.wrap_width);
		},
		renderThumbStyle(p) {
			const style = {};
			if (p === 'x') {
				let translate = `translateX(${this.horizontal_thumb_translate}px)`;
				style.width = `${this.horizontal_thumb_width}px`;
				style.transform = translate;
			} else {
				let translate = `translateY(${this.vertical_thumb_translate}px)`;
				style.height = `${this.vertical_thumb_height}px`;
				style.transform = translate;
			}
			return style;
		},
		horizontalScroll(e) {
			e.preventDefault();
			this.hflag = true;
			this.hstart = e.clientX;
			on(document, 'mousemove', this.hmousemovehandler);
			on(document, 'mouseup', this.hmouseuphandler);
		},
		hmousemovehandler(e) {
			e.preventDefault();
			if (this.hflag) {
				let disX = e.clientX - this.hstart;
				this.hstart = e.clientX;
				this.setLeft(disX);
			}
		},
		setLeft(disX) {
			if (this.horizontal_thumb_translate + disX >= this.bar_width - this.horizontal_thumb_width) {
				this.horizontal_thumb_translate = this.bar_width - this.horizontal_thumb_width;
				let scrollLeft =
					(this.scroll_width - this.wrap_width) *
					this.horizontal_thumb_translate /
					(this.bar_width - this.horizontal_thumb_width);
				this.$refs['scrollbar-wrap'].scrollLeft = scrollLeft;
				if (this.hstart || this.hClick) {
					this.$emit('scrollLeft', scrollLeft);
				}
			} else if (this.horizontal_thumb_translate < 0) {
				this.horizontal_thumb_translate = 0;
			} else {
				this.horizontal_thumb_translate = this.horizontal_thumb_translate + disX;

				if (this.horizontal_thumb_translate < 0) {
					this.horizontal_thumb_translate = 0;
				}
				let scrollLeft =
					(this.scroll_width - this.wrap_width) *
					this.horizontal_thumb_translate /
					(this.bar_width - this.horizontal_thumb_width);
				this.$refs['scrollbar-wrap'].scrollLeft = scrollLeft;
				if (this.hstart || this.hClick) {
					this.$emit('scrollLeft', scrollLeft);
				}
			}
		},
		hmouseuphandler() {
			this.hflag = false;
			off(document, 'mousemove', this.hmousemovehandler);
		},
		verticalScroll(ev) {
			ev.preventDefault();
			this.vflag = true;
			this.vstart = ev.clientY;
			on(document, 'mousemove', this.vmousemovehandler);
			on(document, 'mouseup', this.vmouseuphandler);
		},
		vmousemovehandler(e) {
			e.preventDefault();
			if (this.vflag) {
				let disY = e.clientY - this.vstart;
				this.vstart = e.clientY;
				if (disY < 0 || this.vertical_thumb_translate < this.bar_height - this.vertical_thumb_height) {
					this.setTop(disY);
				}
			}
		},
		vmouseuphandler() {
			this.vflag = false;
			off(document, 'mousemove', this.vmousemovehandler);
		},
		setTop(disY) {
			if (this.vertical_thumb_translate + disY >= this.bar_height - this.vertical_thumb_height) {
				this.vertical_thumb_translate = this.bar_height - this.vertical_thumb_height;
				let scrollTop =
					(this.scroll_height - this.wrap_height) *
					this.vertical_thumb_translate /
					(this.bar_height - this.vertical_thumb_height);
				this.$refs['scrollbar-wrap'].scrollTop = scrollTop;
				if (this.vflag || this.vClick) {
					this.$emit('scrollTop', scrollTop);
				}
				this.$emit('toBottom');
			} else if (this.vertical_thumb_translate < 0) {
				this.vertical_thumb_translate = 0;    
			} else {
				this.vertical_thumb_translate = this.vertical_thumb_translate + disY;
				if (this.vertical_thumb_translate < 0) {
					this.vertical_thumb_translate = 0;
				}
				let scrollTop =
					(this.scroll_height - this.wrap_height) *
					this.vertical_thumb_translate /
					(this.bar_height - this.vertical_thumb_height);
				this.$refs['scrollbar-wrap'].scrollTop = scrollTop;
				if (this.vflag || this.vClick) {
					this.$emit('scrollTop', scrollTop);
				}
			}
		},
		clickVBar(e) {
			if (!this.vertical_thumb_height) return;
			this.vClick = true;
			let disY = e.offsetY - this.vertical_thumb_height / 2 - this.vertical_thumb_translate;
			this.setTop(disY);
			this.vClick = false;
		},
		clickHBar(e) {
			if (!this.horizontal_thumb_width) return;
			this.hClick = true;
			let disX = e.offsetX - this.horizontal_thumb_width / 2 - this.horizontal_thumb_translate;
			this.setLeft(disX);
			this.hClick = false;
		},
		resizehandler() {
			if (!this.open) return;
			this.thumbSize();
		},
		resize() {
			if (!this.open) return;
			this.thumbSize();
		},
	},
	mounted() {
		on(window, 'resize', this.resizehandler);
		this.$nextTick(() => {
			if (this.open) {
				this.thumbSize();
			}
		});
	},
	updated() {
		this.$nextTick(() => {
			if (!this.open) return;
			if (
				this.scroll_height !== this.$refs['scrollbar-wrap'].children[0].offsetHeight ||
				this.scroll_width !== this.$refs['scrollbar-wrap'].children[0].scrollWidth
			) {
				this.thumbSize();
			}
		});
	},
	destroyed() {
		off(document, 'mouseup', this.vmouseuphandler);
		off(document, 'mouseup', this.hmouseuphandler);
		off(window, 'resize', this.resizehandler);
	},
};
</script>
<style lang="less">
.my-scrollbar,
.scrollbar-box,
.common-scrollbar {
	position: relative;
	width: 100%;
	height: 100%;
}
.common-scrollbar {
	overflow: auto;
}
.my-scrollbar.visible .scrollbar_thumb {
	background-color: hsla(220, 4%, 58%, 0.5);
}
.my-scrollbar.visible .ivu-icon {
	opacity:1;
}
.my-scrollbar:hover .ivu-icon {
	opacity:1;
}
.my-scrollbar.horizontal:hover .scrollbar_thumb {
	background-color: hsla(220, 4%, 58%, 0.8);
}

.my-scrollbar.vertical:hover .scrollbar_thumb {
	background-color: hsla(220, 4%, 58%, 0.8);
}
.scrollbar_thumb {
	border-radius: 2px;
}
.scrollbar_wrap {
	overflow: hidden;
	height: inherit;
	max-height: inherit;
	width: inherit;
	max-width: inherit;
}

.scrollbar_bar {
	position: absolute;
	height: 100%;
	border-radius: 4px;
	opacity: 1;
	transition: opacity 0.12s ease-out;
	word-wrap: nowrap;
	&.is-horizontal {
		height: 7px;
		width: 100%;
		bottom: 0px;
		left: 0;
		z-index: 11;
		&.top {
			top: -6px;
		}
	}
	&.is-vertical {
		width: 7px;
		height: 100%;
		right: 0px;
		top: 0;
		z-index: 11;
		&.left {
			left: 0px;
		}
		.thumb-d {
		position:absolute;
		bottom:0;
	}
	}
	.ivu-icon {
	  display:block;
	  opacity: 0;
	  color:rgba(144, 146, 152, 0.5);
	  &:hover {
		  color: rgba(144, 146, 152, 1);
	  }
	  &.disabled {
		  &:hover {
		  color: rgba(144, 146, 152, 0.5);
	      }
	  }
	}
	.scrollbar-box .my-scrollbar .scrollbar_thumb {
		position: relative;
		display: block;
		width: 0;
		height: 0;
		border-radius: inherit;
		background-color: hsla(220, 4%, 58%, 0);
		transition: transform 0.2s;
		&.move {
			background-color: hsla(220, 4%, 58%, 0.8);
		}
	}
}

.scrollbar_bar.is-horizontal .scrollbar_thumb {
	height: 7px;
}

.scrollbar_bar.is-vertical .scrollbar_thumb {
	width: 7px;
}
</style>
